export default {
    props: {
      isFixed: {
        // 是否为固定定位
        type: Boolean,
        default: true,
      },
      top: {
        //初始top
        type: Number,
        default: 200,
      },
      left: {
        //初始left
        type: Number,
        default: window.innerWidth / 2,
      },
      width: {
        //初始宽
        type: Number,
        default: 300,
      },
      height: {
        // 初始高
        type: Number,
        default: 200,
      },
  
      zIndex: {
        // 设置z-index层级
        type: Number,
        default: 0,
      },
      isScale: {
        // 是否可以缩放 默认false
        type: Boolean,
        default: false,
      },
    },
    data() {
      return {
        display: false, //伸缩的显示隐藏
        attrs: ["tl", "tm", "tr", "lm", "rm", "bl", "bm", "br"],
        offsetX: 0, //记录鼠标在拖拽主体的offsetX
        offsetY: 0, //记录鼠标拖拽主体的offsetY
        dragObj: null,
        stick: null, //八个点的dom元素
        clientX: 0, //记录clientX
        clientY: 0, //记录clientY
        topScope: this.top,
        leftScope: this.left,
        isFixedScope: this.isFixed,
        wScope: this.width,
        hScope: this.height,
        zIndexScope: this.zIndex,
        Target: null, //记录鼠标作用的dom元素
        Styles: null, //记录样式
      };
    },
    methods: {
      l(left) {
        return {
          left: left + "px",
        };
      },
      r(right) {
        return {
          right: right + "px",
        };
      },
      t(top) {
        return {
          top: top + "px",
        };
      },
      b(bottom) {
        return {
          bottom: bottom + "px",
        };
      },
      // 定位右上
      positionRight() {
          //这里减的17其实是滚动条的宽度
        const right =
          window.innerWidth -
          parseInt(this.Styles.left) -
          parseInt(this.$el.style.width) -
          17;
        this.$delete(this.Styles, "left");
        this.Styles = Object.assign(this.Styles, this.r(right));
      },
      // 定位左上
      positionTop() {
        const top =
          window.innerHeight -
          parseInt(this.Styles.bottom) -
          parseInt(this.$el.style.height);
        this.$delete(this.Styles, "bottom");
        this.Styles = Object.assign(this.Styles, this.t(top));
      },
      // 定位左下
      positionBottom() {
        const bottm =
          window.innerHeight -
          parseInt(this.Styles.top) -
          parseInt(this.$el.style.height) +
          0.5;
        this.$delete(this.Styles, "top");
        this.Styles = Object.assign(this.Styles, this.b(bottm));
      },
      // 定位左上
      positionLeft() {
           //这里减的17其实是滚动条的宽度
        const left =
          window.innerWidth -
          parseInt(this.Styles.right) -
          parseInt(this.$el.style.width) -
          17;
        this.$delete(this.Styles, "right");
        this.Styles = Object.assign(this.Styles, this.l(left));
      },
  
      down(e) {
        this.Target = e.target;
        const styleAttr = `
                          -webkit-user-select: none;
                          -moz-user-select: none;
                          -ms-user-select: none;
                          user-select: none;
                      `;
        const { offsetX, offsetY } = e;
        // 记录
        this.offsetX = offsetX;
        this.offsetY = offsetY;
        document.body.setAttribute("style", styleAttr);
        document.addEventListener("mousemove", this.move);
      },
      move(e) {
        const { clientX, clientY } = e;
        // 鼠标移动的时候 top值就等于 clientY - 鼠标在元素上的offsetY值
        this.Styles.top = clientY - this.offsetY + "px";
        // 鼠标移动的时候 left值就等于 鼠标的clientX - 鼠标的offsetX值
        this.Styles.left = clientX - this.offsetX + "px";
        //最后深拷贝一下
        this.Styles = JSON.parse(JSON.stringify(this.Styles));
      },
      // 按住顶部的点进行伸缩
      tmMove(e) {
        const { clientY } = e;
        //按住顶部中点的之后 实际上只改变组件的高度
        //鼠标移动时 组件的高度就等于      组件高度 + 鼠标按下时的clientY - 鼠标移动时变化的clientY
        //                                              这里因为顶点在上面 往下移动组件高度减少 往上移动组件高度增加 故 旧值减新值
        this.Styles.height =
          parseInt(this.Styles.height) + this.clientY - clientY + "px";
        //最后把移动时的clientY在赋值给 按下时的clientY使其成为新的clientY
        this.clientY = clientY;
      },
      //按住底部的点进行伸缩
      bmMove(e) {
        const { clientY } = e;
        //按住底部中点的之后 实际上只改变组件的高度
        //鼠标移动时 组件的高度就等于      组件高度 +  鼠标移动时变化的clientY - 鼠标按下时的clientY
        //                                              这里因为顶点在下面 往下移动组件高度增加 往上移动组件高度减少 故 新值减旧值
        this.Styles.height =
          parseInt(this.Styles.height) + clientY - this.clientY + "px";
        //最后把移动时的clientY在赋值给 按下时的clientY使其成为新的clientY
        this.clientY = clientY;
      },
      // 按住右边的点进行伸缩
      rmMove(e) {
        const { clientX } = e;
        //按住右边中点的之后 实际上只改变组件的宽度
        //鼠标移动时 组件的宽度就等于      组件宽度 +  鼠标移动时变化的clientX - 鼠标按下时的clientX
        //                                              这里因为顶点在右面 往左移动组件宽度减少 往右移动组件宽度增加 故 旧值减新值
        this.Styles.width =
          parseInt(this.Styles.width) + clientX - this.clientX + "px";
        //最后把移动时的clientX在赋值给 按下时的clientX使其成为新的clientX
        this.clientX = clientX;
      },
      //按住左边的点进行伸缩
      lmMove(e) {
        const { clientX } = e;
        //按住左边中点的之后 实际上只改变组件的宽度
        //鼠标移动时 组件的宽度就等于      组件宽度 +  鼠标按下时的clientX - 鼠标移动时变化的clientX
        //                                              这里因为顶点在左面  往左移动组件宽度增加 往右移动组件宽度减少  故 新值减旧值
        this.Styles.width =
          parseInt(this.Styles.width) + this.clientX - clientX + "px";
        //最后把移动时的clientX在赋值给 按下时的clientX使其成为新的clientX
        this.clientX = clientX;
      },
      //按住右下点进行伸缩
      brMove(e) {
        const { clientX, clientY } = e;
        //然后是右下点伸缩
        //其实就是调 下边中点和右边中点移动的函数即可
        this.bmMove({ clientY });
        this.rmMove({ clientX });
      },
      //按住右上点进行伸缩
      trMove(e) {
        const { clientX, clientY } = e;
        //右上点伸缩
        //调 上边中点和右边中点移动的函数即可
        this.tmMove({ clientY });
        this.rmMove({ clientX });
      },
      //按住左下点进行缩放
      blMove(e) {
        const { clientX, clientY } = e;
        //左下点伸缩
        //调 下边中点和左边中点移动的函数即可
        this.lmMove({ clientX });
        this.bmMove({ clientY });
      },
      //左上点
      tlMove(e) {
        //左上点伸缩
        //调 上边中点和左边中点移动的函数即可
        const { clientX, clientY } = e;
        this.tmMove({ clientY });
        this.lmMove({ clientX });
      },
      //按住八个点 都会执行的
      stickDown(e) {
        const { clientX, clientY } = e;
        //保存client值
        this.clientY = clientY;
        this.clientX = clientX;
        this.Target = e.target;
        // 给body设置样式使其在拖拽时不能选中
        const styleAttr = `
                          -webkit-user-select: none;
                          -moz-user-select: none;
                          -ms-user-select: none;
                          user-select: none;
                      `;
        document.body.setAttribute("style", styleAttr); //添加一个左键移动是不允许选中的行为
        if (e.target.className.indexOf("tr") !== -1) {
          // 右上方向 左下定点
          this.positionBottom();
          document.addEventListener("mousemove", this.trMove);
        }
        if (e.target.className.indexOf("bl") !== -1) {
          // 左下方向 右上定点
          this.positionRight();
          document.addEventListener("mousemove", this.blMove);
        }
        if (e.target.className.indexOf("tl") !== -1) {
          // 左上方向  右边定点 下面定点
          this.positionBottom();
          this.positionRight();
          document.addEventListener("mousemove", this.tlMove);
        }
        if (e.target.className.indexOf("tm") !== -1) {
          // 上中方向
          this.positionBottom();
          document.addEventListener("mousemove", this.tmMove);
        }
        if (e.target.className.indexOf("rm") !== -1) {
          // 右中方向
          document.addEventListener("mousemove", this.rmMove);
        }
        if (e.target.className.indexOf("lm") !== -1) {
          // 左中方向  将右边改成定点
          this.positionRight();
          document.addEventListener("mousemove", this.lmMove);
        }
        if (e.target.className.indexOf("bm") !== -1) {
          // 下中方向
          document.addEventListener("mousemove", this.bmMove);
        }
        if (e.target.className.indexOf("br") !== -1) {
          // 右下方向
          document.addEventListener("mousemove", this.brMove);
        }
      },
      //鼠标在document范围内抬起执行的函数
      removeEvent(e) {
        if (!this.Target) return;
        const attrs = this.Target.getAttribute("eventCallback");
        //如果说 伸缩的目标元素是顶部三个点 那么就恢复默认的以顶部来定位
        /**
         * 为什么要做恢复这一步操作呢?
         * 因为在按住上面的顶点在拉伸时,我做的操作是把top属性删掉 然后算出bottom的值取而代之
         * 为什么这样做?
         * 首先我们拉住上面的顶点做 组件高度的增加时 组价默认的会向下增加高度 而不会向上增加高度
         * 所以我就想把bottom固定住,这样你高度增加或减少都会往上去
         *
         * 下面恢复left属性也是同理,我在左边拉伸时默认只会影响右边,那我就把right的值算好取而代之
         * 鼠标抬起时一切都恢复到原位
         */
        if (attrs == "tm" || attrs == "tr" || attrs == "tl") {
          //恢复默认的top属性
          this.positionTop();
        }
        if (attrs == "lm" || attrs == "bl" || attrs == "tl") {
          // 恢复默认的left属性
          this.positionLeft();
        }
        //鼠标抬起移除按住组件到处拖的事件
        document.removeEventListener("mousemove", this.move);
        //移除按住下面中点拉伸的事件
        document.removeEventListener("mousemove", this.bmMove);
        //移除按住右边中点拉伸的事件
        document.removeEventListener("mousemove", this.rmMove);
        // 移除按住右下点拉伸的事件
        document.removeEventListener("mousemove", this.brMove);
        // 移除左边中点拉伸的事件
        document.removeEventListener("mousemove", this.lmMove);
        // 移除上面中点拉伸的事件
        document.removeEventListener("mousemove", this.tmMove);
        // 移除右上点拉伸的事件
        document.removeEventListener("mousemove", this.trMove);
        //移除左下点拉伸的事件
        document.removeEventListener("mousemove", this.blMove);
        // 移除左上点拉升的事件
        document.removeEventListener("mousemove", this.tlMove);
        // 移除默认选中的行为  (就是你鼠标拖拽的时候有时会默认选中页面中的文字或者图片之类的就很影响用户体验)
        //所以在拖拽期间我就不让鼠标产生这种行为
        document.body.setAttribute("style", ""); //去除默认选中的行为
        this.Target = null; //将事件对象赋值为空 以防对后面行为的事件的干扰
      },
      // 点击组件区域就显示点 否则就不显示
      showStick(e) {
        const array = [e.path[0], e.path[1], e.path[2], e.path[3]];
        for (let index = 0; index < array.length; index++) {
          const element = array[index];
          const classNames = element.className;
          if (classNames.indexOf("stick") != -1) {
            this.display = true;
            return;
          }
        }
        this.display = false;
      },
    },
    mounted() {
      // 拖拽的主体是 this.$el中的第一个元素
      this.dragObj = this.$el.firstElementChild;
      // 初始化一下样式
      this.Styles = JSON.parse(
        JSON.stringify(
          Object.assign(
            this.sizeStyle,
            this.t(this.topScope),
            this.l(this.leftScope)
          )
        )
      );
      // 获取8个dom元素
      this.sticks = this.$el.getElementsByClassName("base");
      //   伸缩框8个点的按下事件的绑定
      for (const item of this.sticks) {
        item.addEventListener("mousedown", this.stickDown);
      }
  
      // 拖拽主体的事件绑定
      this.dragObj.addEventListener("mousedown", this.down);
      //    给文档对象绑定一个鼠标抬起的事件
      document.addEventListener("mouseup", this.removeEvent);
      //给body绑定一个点击事件
      document.body.addEventListener("click", this.showStick);
    },
    beforeDestroy() {
      //移除 抬起事件
      document.removeEventListener("mouseup", this.removeEvent);
      // 移除点击事件
      document.body.removeEventListener("click", this.showStick);
      // 移除8个点的按下事件
      for (const item of this.stick) {
        item.removeEventListener("mousedown", this.stickDown);
      }
    },
    computed: {
      sizeStyle() {
        return {
          position: this.isFixedScope ? "fixed" : "absolute",
          width: this.wScope + "px",
          height: this.hScope + "px",
          "z-index": this.zIndexScope ? this.zIndexScope : "auto",
        };
      },
    },
  };